package com.example.myapplication.slice;

import com.example.baselib.base.BaseAbilitySlice;
import com.example.baselib.utils.SDCardUtils;
import com.example.baselib.utils.UIUtils;
import com.example.baselib.utils.log.LogUtils;
import com.example.myapplication.ResourceTable;
import com.example.myapplication.data.EConstants;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.graphics.Surface;
import ohos.agp.graphics.SurfaceOps;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.media.camera.CameraKit;
import ohos.media.camera.device.*;
import ohos.media.image.Image;
import ohos.media.image.ImageReceiver;
import ohos.media.image.common.ImageFormat;
import ohos.media.image.common.Size;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PICTURE;
import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVIEW;

public class AvatarAbilitySlice extends BaseAbilitySlice {

    CameraAbility cameraAbility;
    ImageReceiver imageReceiver;
    SurfaceProvider mSurfaceProvider;
    Surface mSurface;
    Camera mCamera;

    EventHandler handler = new EventHandler(EventRunner.create("camera"));
    File myFile;

    // 单帧捕获生成图像回调Listener
    private final ImageReceiver.IImageArrivalListener imageArrivalListener = new ImageReceiver.IImageArrivalListener() {
        //拍照完成后数据回调
        @Override
        public void onImageArrival(ImageReceiver imageReceiver) {
            StringBuffer fileName = new StringBuffer("picture_");
            fileName.append(UUID.randomUUID()).append(".jpg"); // 定义生成图片文件名
            myFile = new File(SDCardUtils.getPicturesDir(getAbility()), fileName.toString()); // 创建图片文件
            final Image myImage = imageReceiver.readNextImage();
            // 执行读写线程任务生成图片
            handler.postTask(new Runnable() {
                @Override
                public void run() {
                    if (myFile == null) {
                        LogUtils.e("onImageArrival(ImageReceiver) 创建图片文件失败");
                        return;
                    }
                    Image.Component component = myImage.getComponent(ImageFormat.ComponentType.JPEG);
                    byte[] bytes = new byte[component.remaining()];
                    component.read(bytes);
                    FileOutputStream output = null;
                    try {
                        output = new FileOutputStream(myFile);
                        output.write(bytes); // 写图像数据
                        Intent intent = new Intent();
                        intent.setParam("test", myFile.getAbsolutePath());
                        getAbility().setResult(EConstants.REQUEST_CODE_CAMERA, intent);
                        terminateAbility();
                    } catch (IOException e) {
                        LogUtils.e(e.getLocalizedMessage());
                    } finally {
                        if (output != null) {
                            try {
                                output.close(); // 关闭流
                            } catch (IOException e) {
                                LogUtils.e(e.getLocalizedMessage());
                            }
                        }
                        myImage.release();
                    }
                }
            });
        }
    };

    private void takePictureInit() {
        List<Size> sizes = cameraAbility.getSupportedSizes(ImageFormat.JPEG);
        Size size = sizes.get(0);
        imageReceiver = ImageReceiver.create(Math.max(size.width, size.height),
                Math.min(size.width, size.height), ImageFormat.JPEG, 5); // 创建ImageReceiver对象，注意create函数中宽度要大于高度；5为最大支持的图像数，请根据实际设置。
        imageReceiver.setImageArrivalListener(imageArrivalListener);
    }

    @Override
    protected int initResLayoutId() {
        return ResourceTable.Layout_ability_avater;
    }

    @Override
    protected void initComponent() {
        super.initComponent();
        getWindow().setTransparent(true);
        mSurfaceProvider = UIUtils.findComponentFromId(this, ResourceTable.Id_surface_provider);
        mSurfaceProvider.pinToZTop(false);
        mSurfaceProvider.getSurfaceOps().get().addCallback(new SurfaceCallBack());

        Button button = UIUtils.findComponentFromId(this, ResourceTable.Id_btn_camera);
        button.setClickedListener((component -> {
            capture();
        }));
        LogUtils.i("initComponent");
    }

    private void capture() {
        if (mCamera == null) {
            LogUtils.i("拍照失败 Camera == null");
            return;
        }
        FrameConfig.Builder frameConfigBuilder = mCamera.getFrameConfigBuilder(FRAME_CONFIG_PICTURE);
        if (frameConfigBuilder == null) {
            LogUtils.i("拍照失败 FrameConfig.Builder = null");
            return;
        }
        frameConfigBuilder.addSurface(mSurface);
        frameConfigBuilder.addSurface(imageReceiver.getRecevingSurface());
        frameConfigBuilder.setImageRotation(90);
        try {
            mCamera.triggerSingleCapture(frameConfigBuilder.build());
            LogUtils.i("拍照完成");
        } catch (IllegalArgumentException e) {
            LogUtils.e(e.getLocalizedMessage());
        } catch (IllegalStateException e) {
            LogUtils.e(e.getLocalizedMessage());
        }

    }


    private void openCamera() {
        CameraKit cameraKit = CameraKit.getInstance(this);
        if (cameraKit == null) {
            LogUtils.d("获取相机实例失败");
            return;
        }
        try {

            String[] cameraIds = cameraKit.getCameraIds();
            if (cameraIds.length <= 0) {
                LogUtils.d("获取可用相机失败");
                return;
            }
            cameraAbility = cameraKit.getCameraAbility(cameraIds[0]);
            takePictureInit();
            cameraKit.createCamera(cameraIds[0], new CameraStateCallbackImpl(), handler);
        } catch (Exception e) {
            LogUtils.e(e.getLocalizedMessage());
            e.printStackTrace();
        }

    }

    class SurfaceCallBack implements SurfaceOps.Callback {

        @Override
        public void surfaceCreated(SurfaceOps surfaceOps) {
            mSurface = surfaceOps.getSurface();
            openCamera();
            LogUtils.i("surfaceCreated Surface : %s", mSurface == null ? "null" : mSurface.toString());
        }

        @Override
        public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) {
            LogUtils.i("surfaceChanged ");
        }

        @Override
        public void surfaceDestroyed(SurfaceOps surfaceOps) {
            LogUtils.i("surfaceDestroyed");
        }
    }

    class CameraStateCallbackImpl extends CameraStateCallback {

        @Override
        public void onCreated(Camera camera) {
            super.onCreated(camera);
            if (mSurface == null) {
                LogUtils.i("onCreated  mSurface == null");
                return;
            }
            CameraConfig.Builder configBuilder = camera.getCameraConfigBuilder();
            //配置预览
            configBuilder.addSurface(mSurface);
            //配置拍照
            configBuilder.addSurface(imageReceiver.getRecevingSurface());
            configBuilder.setFrameStateCallback(new FrameStateCallbackImpl(), handler);
            try {
                camera.configure(configBuilder.build());
                mCamera = camera;
            } catch (IllegalArgumentException e) {
                LogUtils.e(e.getLocalizedMessage());
            } catch (IllegalStateException e) {
                LogUtils.e(e.getLocalizedMessage());
            }
            LogUtils.i("onCreated");
        }

        @Override
        public void onConfigured(Camera camera) {
            super.onConfigured(camera);
            // 获取预览配置模板
            FrameConfig.Builder frameConfigBuilder = camera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
            // 配置预览Surface
            frameConfigBuilder.addSurface(mSurface);
            // 配置拍照其他参数
            frameConfigBuilder.setZoom(1.2f);
            try {
                // 启动循环帧捕获
                int triggerId = camera.triggerLoopingCapture(frameConfigBuilder.build());
                LogUtils.i("循环帧扑获 : " + triggerId);
            } catch (IllegalArgumentException e) {
                LogUtils.e(e.getLocalizedMessage());
            } catch (IllegalStateException e) {
                LogUtils.e(e.getLocalizedMessage());
            }
            LogUtils.i("onConfigured");
        }

        @Override
        public void onCaptureRun(Camera camera) {
            super.onCaptureRun(camera);
            LogUtils.i("onCaptureRun");
        }

        @Override
        public void onReleased(Camera camera) {
            super.onReleased(camera);
            if (camera != null) {
                // 关闭相机和释放资源
                camera.release();
                camera.stopLoopingCapture();
                camera = null;
            }
            LogUtils.i("onReleased");
        }
    }


    class FrameStateCallbackImpl extends FrameStateCallback {
        @Override
        public void onFrameStarted(Camera camera, FrameConfig frameConfig, long frameNumber, long timestamp) {
            super.onFrameStarted(camera, frameConfig, frameNumber, timestamp);
            LogUtils.i("onFrameStarted");
        }

        @Override
        public void onFrameProgressed(Camera camera, FrameConfig frameConfig, FrameResult frameResult) {
            super.onFrameProgressed(camera, frameConfig, frameResult);
            LogUtils.i("onFrameProgressed");
        }

        @Override
        public void onFrameFinished(Camera camera, FrameConfig frameConfig, FrameResult frameResult) {
            super.onFrameFinished(camera, frameConfig, frameResult);
            LogUtils.i("onFrameFinished");
        }

        @Override
        public void onFrameError(Camera camera, FrameConfig frameConfig, int errorCode, FrameResult frameResult) {
            super.onFrameError(camera, frameConfig, errorCode, frameResult);
            LogUtils.i("onFrameError");
        }
    }


}
